#include <stdio.h>
#include <string.h>
#include <string>

#include "memrec.h"
#include "Config.h"
#define new DBG_NEW



tSection::tSection():
sec_name(NULL)
{
}

tSection::~tSection()
{
}

void tSection::clear()
{
	if (sec_name)
		delete sec_name;
	sec_name = NULL;
	for (unsigned int i = 0; i < opts.size(); i++)
	{
		delete opts[i].first;
		delete opts[i].second;
	}
	opts.clear();
}

void tSection::reset()
{
	sec_name = NULL;
	opts.clear();
}

bool tSection::GetOptInt(const char * opt, int * val)
{
	unsigned int i = 0;
	for (i = 0; i < opts.size(); i++)
	{
		if (strcmp(opts[i].first, opt) == 0)
		{
			*val = strtol(opts[i].second, NULL, 10);
			return true;
		}
	}
	return false;
}

char* tSection::GetOptStr(const char * opt)
{
	for (unsigned int i = 0; i < opts.size(); i++)
	{
		if (strcmp(opts[i].first, opt) == 0)
		{
			return opts[i].second;
		}
	}
	return NULL;
}

tConfig::tConfig()
{	
}

int tConfig::SkipSpaceChar(char ** buf)
{
	char * _buf = *buf;
    while(*_buf) 
	{
		if( *_buf != ' ' && *_buf != '\t') 
		{
			break; 
		}
		_buf++;
    }
	*buf = _buf;
	return 0;
}

bool tConfig::EndOfLine(char *buf)
{
	return (*buf == '\n' || *buf == '\r');
}

int tConfig::ReadWord(char **buf, char ** word)
{
	char * _buf = *buf;
	SkipSpaceChar(&_buf);
	if (EndOfLine(_buf))
		return -1;
	int len = 0;
	char* start = _buf;
    while(*_buf) 
	{
		if( *_buf==' ' || *_buf=='\t' || *_buf=='\r' || *_buf=='\n') 
		{
			break; 
		}
		len++;
		_buf++;
    }
	*word = new char[len+1];
	memset(*word, 0, len+1);
	strncpy(*word, start, len);
	*buf = _buf;
	return 0;
}

int tConfig::ParseLine(char ** option, char ** value)
{
	if (file == NULL)
		return -1;
	char line[1024];
	if (fgets(line, sizeof(line), file) == 0)
		return -2;

	if (line[0] == '#')
		return -1;
	if (line[0] == '[')
	{
		ParseSectionName(line);
		return 0;
	}

	char * buf = line;
	//read option
	if (ReadWord(&buf, option) != 0)
		return -1;
	//read operator
	char * operate = NULL;
	if (ReadWord(&buf, &operate) != 0)
		return -1;
	if (operate[0] !='=')
	{
		delete[] operate;
		return -1;
	}
	else
		delete[] operate;
	//read value
	if (ReadWord(&buf, value) != 0)
		return -1;
	return 0;
}

int tConfig::ParseSectionName(const char * buf)
{
	buf++;
	const char *rightbket = strchr(buf, ']');
	if (!rightbket)
		return -1;
	unsigned int length = rightbket - buf;
	if (length == 0)
		return -1;
	char * sec_name = new char[length+1];
	strncpy(sec_name, buf, length);
	sec_name[length] = 0;
	if (m_CurSec.sec_name)
		sections.push_back(m_CurSec);	
	m_CurSec.reset();
	m_CurSec.sec_name = sec_name;
	return 0; 
}

int tConfig::LoadConfig(const char * configfile)
{
	file = fopen(configfile, "r");
	if (file == NULL)
		return -1;
	char * opt = NULL, * val = NULL;
	while (ParseLine(&opt, &val) != -2)
	{
		if (opt && val)
		{
			if (m_CurSec.sec_name == NULL)
				opts.push_back(std::pair<char*,char*>(opt, val));
			else
				m_CurSec.opts.push_back(std::pair<char*,char*>(opt, val));
		}
		opt = val = NULL;
	}
	if (m_CurSec.sec_name)
		sections.push_back(m_CurSec);
	m_CurSec.reset();
	fclose(file);
	return 0;
}

bool tConfig::GetOptInt(const char * opt, int * val)
{
	unsigned int i = 0;
	for (i = 0; i < opts.size(); i++)
	{
		if (strcmp(opts[i].first, opt) == 0)
		{
			*val = strtol(opts[i].second, NULL, 10);
			return true;
		}
	}
	return false;
}

char* tConfig::GetOptStr(const char * opt)
{
	for (unsigned int i = 0; i < opts.size(); i++)
	{
		if (strcmp(opts[i].first, opt) == 0)
		{
			return opts[i].second;
		}
	}
	return NULL;
}

int tConfig::SetConfig(int index, char * strval)
{
	return 0;
}

tConfig::~tConfig()
{
	for (unsigned int i = 0; i < opts.size(); i++)
	{
		delete opts[i].first;
		delete opts[i].second;
	}
	for (unsigned int i = 0; i < sections.size(); i++)
	{
		sections[i].clear();
	}
}

tSection* tConfig::GetSection(const char * sec_name)
{
	for (unsigned int i = 0; i < sections.size(); i++)
	{
		if (strcmp(sections[i].sec_name, sec_name) == 0)
			return &sections[i];
	}
	return NULL;
}

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

